package com.fjec.activity.service.impl;

import cn.hutool.json.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fjec.activity.entity.*;
import com.fjec.activity.feign.MarketClient;
import com.fjec.activity.mapper.BizActivitySeckillMapper;
import com.fjec.activity.service.*;
import com.fjec.activity.util.MarketUtil;
import com.fjec.activity.view.SecKillShopVO;
import com.fjec.activity.view.UserGiftVO;
import com.fjec.common.Const;
import com.fjec.common.exception.BizException;
import com.fjec.common.protocol.JsonResult;
import com.fjec.common.shiro.AccountInfo;
import com.fjec.common.util.BusinessUtil;
import com.fjec.common.util.DateUtil;
import com.fjec.common.util.JsonUtil;
import com.fjec.common.util.SpecialMapUtil;
import org.apache.commons.collections.MapUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

/**
 * <p>
 * 004.发布秒杀活动表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2020-09-18
 */
@Service
@Transactional
public class BizActivitySeckillServiceImpl extends ServiceImpl<BizActivitySeckillMapper, BizActivitySeckill> implements IBizActivitySeckillService {

    @Resource
    private BizActivitySeckillMapper mapper;

    @Resource
    private IBizActivitySeckillGiftService bizActivitySeckillGiftService;

    @Resource
    private IBizActivitySeckillConditionService bizActivitySeckillConditionService;

    @Resource
    private IBizGiveGiftService bizGiveGiftService;

    @Resource
    private IBizUserGiftService bizUserGiftService;

    @Resource
    private IBizUserGiftChangeRecordService bizUserGiftChangeRecordService;

    @Resource
    private IBizActivitySeckillUserService bizActivitySeckillUserService;

    @Autowired
    private MarketClient marketClient;

    @Autowired
    private IRPCService rpcService;

    @Autowired
    private RedisLockRegistry redisLockRegistry;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MarketUtil marketUtil;

    @Value("${fjec:activity:seckill:threshold}")
    private double threshold;

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public int saveSecKill(List<UserGiftVO> userGiftVOList, Integer markCodes, String partInRoles, int startTime) {
        // 首先校验用户当前拥有的礼物是否充足
        Long giveId = AccountInfo.getUserId();
        List<BizUserGift> userGifts = bizUserGiftService.list(new QueryWrapper<BizUserGift>()
                .eq("UserId", giveId));

        List<BizUserGift> bizUserGifts = new ArrayList<>();
        for (UserGiftVO userGiftVO : userGiftVOList) {
            if (userGiftVO.getRequireNum() == null || userGiftVO.getRequireNum() == 0)
                continue;
            Long giftId = userGiftVO.getGiftId();
            Optional<BizUserGift> optionalBizUserGift = userGifts.stream()
                    .filter(ug -> ug.getGiftId().equals(giftId))
                    .findFirst();
            if (optionalBizUserGift.isPresent()) {
                // 用户拥有该礼物，则比较数量
                BizUserGift ug = optionalBizUserGift.get();
                if (ug.getGiftNum() < userGiftVO.getRequireNum())
                    return -1;
                // 更新该礼物剩余数量
                // 更新用户礼物表
                int remaining = ug.getGiftNum() - userGiftVO.getRequireNum();
                ug.setGiftNum(remaining);
                ug.setUpdateTime(DateUtil.nowLdt());
                bizUserGifts.add(ug);
            } else {
                // 用户无此礼物，直接返回failure
                return -1;
            }
        }

        // 秒杀记录
        BizActivitySeckill seckill = new BizActivitySeckill();
        seckill.setTitle("seckill");
        seckill.setBusiId(AccountInfo.getBusiId());
        seckill.setBusiType(AccountInfo.getBusiType());
        seckill.setGiftRemaining(1);
        LocalDateTime localDateTime;
        if (startTime == 0) localDateTime = DateUtil.nowLdt();
        else if (startTime == 1) localDateTime = DateUtil.nowLdt().plusMinutes(10);
        else localDateTime = DateUtil.nowLdt().plusHours(1);
        seckill.setStartTime(localDateTime);
        seckill.setEndTime(DateUtil.nowLdt());
        seckill.setCreateTime(DateUtil.nowLdt());
        this.save(seckill);

        List<BizActivitySeckillGift> seckillGifts = new ArrayList<>();
        List<BizUserGiftChangeRecord> changeRecords = new ArrayList<>();

        for (UserGiftVO userGiftVO : userGiftVOList) {
            if (userGiftVO.getRequireNum() == null || userGiftVO.getRequireNum() == 0)
                continue;

            // 秒杀礼物详情
            BizActivitySeckillGift seckillGift = new BizActivitySeckillGift();
            seckillGift.setSeckillId(seckill.getId());
            seckillGift.setGiftId(userGiftVO.getGiftId());
            seckillGift.setSeckillNum(userGiftVO.getRequireNum());
            seckillGift.setCreateTime(DateUtil.nowLdt());
            seckillGift.setUpdateVer(0);
            int numToBuy = userGiftVO.getRequireNum() - userGiftVO.getGiftNum();
            seckillGift.setBuyNum(Math.max(numToBuy, 0));
            seckillGifts.add(seckillGift);

            // 用户礼物变动记录
            BizUserGiftChangeRecord record = new BizUserGiftChangeRecord();
            record.setUserGiftId(userGiftVO.getId());
            record.setOpeType(4);
            record.setNum(-userGiftVO.getRequireNum());
            record.setBusiData(String.valueOf(seckill.getId()));
            record.setCreateTime(DateUtil.nowLdt());
            changeRecords.add(record);
        }

        bizActivitySeckillGiftService.saveBatch(seckillGifts);

        bizUserGiftService.updateBatchById(bizUserGifts);

        bizUserGiftChangeRecordService.saveBatch(changeRecords);

        List<Integer> roles = Arrays.asList(partInRoles.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList());
        BizActivitySeckillCondition seckillCondition = new BizActivitySeckillCondition();
        seckillCondition.setId(seckill.getId());
        seckillCondition.setMarkCode(markCodes);
        seckillCondition.setPartInRoles(roles.stream().reduce(0, Integer::sum));
        seckillCondition.setCreateTime(DateUtil.nowLdt());
        bizActivitySeckillConditionService.save(seckillCondition);

        return 0;
    }

    @Override
    public Map<String, Object> getSecKillForMe(Page page) {

        Map<String, Object> resultMap = new HashMap<>();
        Integer busiType = AccountInfo.getBusiType();
        if (busiType == 1) {
            resultMap.put("purchase", new ArrayList<>());
            resultMap.put("nonPurchase", new ArrayList<>());
            return resultMap;
        }

        List<Integer> markCodes = marketClient.getMarkCodesByBusiId(AccountInfo.getBusiId(), busiType);

        List<BizActivitySeckillCondition> secKillConditions = bizActivitySeckillConditionService.list(
                new QueryWrapper<BizActivitySeckillCondition>().in("MarkCode", markCodes));

        // 不显示该用户已领取礼物的
        List<BizActivitySeckillUser> bizActivitySeckillUserList = bizActivitySeckillUserService
                .list(new QueryWrapper<BizActivitySeckillUser>().eq("UserId", AccountInfo.getUserId()));
        List<Long> partInSeckillIds = new ArrayList<>();
        bizActivitySeckillUserList.forEach(r -> partInSeckillIds.add(r.getSeckillId()));

        Iterator<BizActivitySeckillCondition> iterator = secKillConditions.iterator();
        Integer role = BusinessUtil.busiType2Bin(busiType);
        List<Long> secKillIds = new ArrayList<>();
        while (iterator.hasNext()) {
            BizActivitySeckillCondition seckillCondition = iterator.next();
            if ((seckillCondition.getPartInRoles() & role) != 0 && !partInSeckillIds.contains(seckillCondition.getId()))
                secKillIds.add(seckillCondition.getId());
        }

        if (secKillIds.size() == 0) {
            resultMap.put("purchase", new ArrayList<>());
            resultMap.put("nonPurchase", new ArrayList<>());
            return resultMap;
        }

        IPage p = this.page(page, new QueryWrapper<BizActivitySeckill>()
                .in("Id", secKillIds)
                .lt("StartTime", DateUtil.nowLdt())
                .eq("GiftRemaining", 1)
//                .orderByAsc("BusiType")
                .orderByAsc("StartTime"));

        List<BizActivitySeckill> allSecKills = p.getRecords();
        resultMap.put("total", p.getTotal());
        // 把采购商和非采购商分隔开，放入两个list
        List<BizActivitySeckill> purchaseSeckills = new ArrayList<>();
        Iterator<BizActivitySeckill> ite = allSecKills.iterator();
        while (ite.hasNext()) {
            BizActivitySeckill seckill = ite.next();
            if (seckill.getBusiType() == 6) {
                purchaseSeckills.add(seckill);
                ite.remove();
            }
        }

        Long userId = AccountInfo.getUserId();
        List<Long> nonPurchaseBusiIds = allSecKills.stream().map(BizActivitySeckill::getBusiId).collect(Collectors.toList());
        List<Long> purchaseBusiIds = purchaseSeckills.stream().map(BizActivitySeckill::getBusiId).collect(Collectors.toList());

        List<SecKillShopVO> nonPurchaseShops = new ArrayList<>();
        if (nonPurchaseBusiIds.size() > 0) {
            JSONArray ja = new JSONArray(marketClient.getShopVOsByBusiIds(nonPurchaseBusiIds, userId));
            List<SecKillShopVO> shopVOS = ja.toList(SecKillShopVO.class);

            allSecKills.forEach(secKill -> {
                Long busiId = secKill.getBusiId();
                Optional<SecKillShopVO> shopVOOpt = shopVOS.stream().filter(s -> s.getId().equals(busiId)).findFirst();
                if (shopVOOpt.isPresent()) {
                    SecKillShopVO secKillShopVO = shopVOOpt.get();
                    SecKillShopVO newSecKillShopVo = new SecKillShopVO();
                    BeanUtils.copyProperties(secKillShopVO, newSecKillShopVo);
                    newSecKillShopVo.setSecKillOrGivingId(secKill.getId());
                    newSecKillShopVo.setSecKillOrGiven(1);
                    nonPurchaseShops.add(newSecKillShopVo);
                }
            });
        }

        List<SecKillShopVO> purchaseShops = new ArrayList<>();
        if (purchaseBusiIds.size() > 0) {
            JSONArray ja = new JSONArray(marketClient.getShopVOsByBusiIds(purchaseBusiIds, userId));
            List<SecKillShopVO> shopVOS = ja.toList(SecKillShopVO.class);

            purchaseSeckills.forEach(secKill -> {
                Long busiId = secKill.getBusiId();
                Optional<SecKillShopVO> shopVOOpt = shopVOS.stream().filter(s -> s.getId().equals(busiId)).findFirst();
                if (shopVOOpt.isPresent()) {
                    SecKillShopVO secKillShopVO = shopVOOpt.get();
                    SecKillShopVO newSecKillShopVo = new SecKillShopVO();
                    BeanUtils.copyProperties(secKillShopVO, newSecKillShopVo);
                    newSecKillShopVo.setSecKillOrGivingId(secKill.getId());
                    newSecKillShopVo.setSecKillOrGiven(1);
                    purchaseShops.add(newSecKillShopVo);
                }
            });
        }

        resultMap.put("nonPurchase", nonPurchaseShops);
        resultMap.put("purchase", purchaseShops);
        return resultMap;
    }

    @Override
    public Map<String, Object> getGivingForMe(Page page) {
        if (!SecurityUtils.getSubject().isAuthenticated())
            return null;
        Map<String,Object> resultMap = new HashMap<>();

        Long userId = AccountInfo.getUserId();
        IPage<BizGiveGift> p = bizGiveGiftService.page(page, new QueryWrapper<BizGiveGift>()
                .eq("ReceId", userId)
                .eq("Received", 0)
                .orderByAsc("BusiType"));
        List<BizGiveGift> allGives = p.getRecords();
        resultMap.put("total", p.getTotal());

        // 把采购商和非采购商分隔开，放入两个list
        List<BizGiveGift> purchaseGives = new ArrayList<>();
        Iterator<BizGiveGift> ite = allGives.iterator();
        while (ite.hasNext()) {
            BizGiveGift give = ite.next();
            if (give.getBusiType() == 6) {
                purchaseGives.add(give);
                ite.remove();
            }
        }

        List<Long> nonPurchaseUserIds = allGives.stream().map(BizGiveGift::getGiveId).collect(Collectors.toList());
        List<Long> purchaseUserIds = purchaseGives.stream().map(BizGiveGift::getGiveId).collect(Collectors.toList());

        if (nonPurchaseUserIds.size() > 0) {
            JSONArray ja = new JSONArray(marketClient.getShopVOsByGivingUserIds(JsonUtil.toJson(nonPurchaseUserIds), userId));
            List<SecKillShopVO> shopVOS = ja.toList(SecKillShopVO.class);
            List<SecKillShopVO> nonPurchaseShops = new ArrayList<>();
            allGives.forEach(bizGiveGift -> {
                Long giverId = bizGiveGift.getGiveId();
                Optional<SecKillShopVO> shopVOOpt = shopVOS.stream().filter(s -> s.getUserId().equals(giverId)).findFirst();
                if (shopVOOpt.isPresent()) {
                    SecKillShopVO secKillShopVO = shopVOOpt.get();
                    SecKillShopVO newSecKillShopVo = new SecKillShopVO();
                    BeanUtils.copyProperties(secKillShopVO, newSecKillShopVo);
                    newSecKillShopVo.setSecKillOrGivingId(bizGiveGift.getId());
                    newSecKillShopVo.setSecKillOrGiven(1);
                    nonPurchaseShops.add(newSecKillShopVo);
                }
            });

            Collections.shuffle(nonPurchaseShops);
            resultMap.put("nonPurchase", nonPurchaseShops);
        } else {
            resultMap.put("nonPurchase", new ArrayList<>());
        }

        if (purchaseUserIds.size() > 0) {
            String jsonStr = marketClient.getShopVOsByGivingUserIds(JsonUtil.toJson(purchaseUserIds), userId);
            JSONArray ja = new JSONArray(jsonStr);
            List<SecKillShopVO> shopVOS = ja.toList(SecKillShopVO.class);

            List<SecKillShopVO> purchaseShops = new ArrayList<>();
            purchaseGives.forEach(secKill -> {
                Long giverId = secKill.getGiveId();
                Optional<SecKillShopVO> shopVOOpt = shopVOS.stream().filter(s -> s.getUserId().equals(giverId)).findFirst();
                if (shopVOOpt.isPresent()) {
                    SecKillShopVO secKillShopVO = shopVOOpt.get();
                    SecKillShopVO newSecKillShopVo = new SecKillShopVO();
                    BeanUtils.copyProperties(secKillShopVO, newSecKillShopVo);
                    newSecKillShopVo.setSecKillOrGivingId(secKill.getId());
                    newSecKillShopVo.setSecKillOrGiven(1);
                    purchaseShops.add(newSecKillShopVo);
                }
            });

            Collections.shuffle(purchaseShops);
            resultMap.put("purchase", purchaseShops);
        } else {
            resultMap.put("purchase", new ArrayList<>());
        }

        return resultMap;
    }

    @Override
    public void doKill(Long userId, Long secKillId, String shopName) {
        Lock lock = redisLockRegistry.obtain(Const.SECKILL_LOCK_KEY + secKillId);

        try {
            lock.lock();
            Random r = new Random();
            boolean got = false;
            double bingo = r.nextDouble();
            if (bingo > (1 - threshold)) {
                List<Map<String, Object>> gifts = bizActivitySeckillGiftService.getGiftsBySeckillId(secKillId);

                Map<String, Object> gift = null;

                List<Map<String, Object>> remainingGifts = gifts.stream()
                        .filter(g -> MapUtils.getInteger(g, "SeckillNum") > 0)
                        .collect(Collectors.toList());
                for (int i = 0; i < remainingGifts.size(); i++) {
                    gift = remainingGifts.get(r.nextInt(remainingGifts.size()));
                    Integer remaining = MapUtils.getInteger(gift, "SeckillNum");
                    if (remaining > 0) {
                        got = true;
                        gift.put("SeckillNum", remaining - 1);
                        break;
                    }
                }
                if (got) {
                    final Long giftId = MapUtils.getLong(gift, "GiftId");
                    // 插入秒杀活动用户抢得礼物表
                    BizActivitySeckillUser bizActivitySeckillUser = new BizActivitySeckillUser();
                    bizActivitySeckillUser.setSeckillId(secKillId);
                    bizActivitySeckillUser.setUserId(userId);
                    bizActivitySeckillUser.setGiftId(giftId);
                    bizActivitySeckillUser.setGiftNum(1);
                    Map<String, Object> userInfo = new HashMap<>();
                    userInfo.put("shopName", shopName);
                    bizActivitySeckillUser.setUserInfo(JsonUtil.toJson(userInfo));
                    bizActivitySeckillUser.setCreateTime(DateUtil.nowLdt());
                    bizActivitySeckillUserService.save(bizActivitySeckillUser);

                    // 用户礼物表
                    BizUserGift userGift = bizUserGiftService.getOne(new QueryWrapper<BizUserGift>()
                            .eq("UserId", userId)
                            .eq("GiftId", giftId));
                    if (userGift != null) {
                        userGift.setGiftNum(userGift.getGiftNum() + 1);
                        userGift.setUpdateTime(DateUtil.nowLdt());
                        bizUserGiftService.updateById(userGift);
                    } else {
                        userGift = new BizUserGift();
                        userGift.setUserId(userId);
                        userGift.setGiftId(giftId);
                        userGift.setGiftNum(1);
                        userGift.setCreateTime(DateUtil.nowLdt());
                        userGift.setUpdateVer(0);
                        bizUserGiftService.save(userGift);
                    }

                    // 用户礼物变动表
                    BizUserGiftChangeRecord changeRecord = new BizUserGiftChangeRecord();
                    changeRecord.setUserGiftId(userGift.getId());
                    changeRecord.setNum(1);
                    changeRecord.setOpeType(5);
                    changeRecord.setBusiData(String.valueOf(secKillId));
                    changeRecord.setCreateTime(DateUtil.nowLdt());
                    bizUserGiftChangeRecordService.save(changeRecord);
                    // 更新redis
                    redisTemplate.opsForValue().set(Const.SECKILL_GIFT_KEY + secKillId, gifts);

                } else {
                    // 更新秒杀活动参与用户表
                    BizActivitySeckillUser seckillUser = new BizActivitySeckillUser();
                    seckillUser.setSeckillId(secKillId);
                    seckillUser.setUserId(userId);
                    seckillUser.setGiftId(0L);
                    seckillUser.setGiftNum(0);
                    seckillUser.setCreateTime(DateUtil.nowLdt());
                    Map<String, Object> userInfo = new HashMap<>();
                    userInfo.put("shopName", shopName);
                    seckillUser.setUserInfo(JsonUtil.toJson(userInfo));
                    bizActivitySeckillUserService.save(seckillUser);
                }
                // 如果当前秒杀活动无剩余礼物，更新DB
                boolean hasRemaining = false;
                for (Map<String, Object> g : gifts) {
                    if (MapUtils.getInteger(g, "SeckillNum") > 0) {
                        hasRemaining = true;
                        break;
                    }
                }
                if (!hasRemaining) {
                    BizActivitySeckill seckill = new BizActivitySeckill();
                    seckill.setId(secKillId);
                    seckill.setGiftRemaining(0);
                    this.updateById(seckill);
                }

            } else {
                // 更新秒杀活动参与用户表
                BizActivitySeckillUser seckillUser = new BizActivitySeckillUser();
                seckillUser.setSeckillId(secKillId);
                seckillUser.setUserId(userId);
                seckillUser.setGiftId(0L);
                seckillUser.setGiftNum(0);
                seckillUser.setCreateTime(DateUtil.nowLdt());
                Map<String, Object> userInfo = new HashMap<>();
                userInfo.put("shopName", shopName);
                seckillUser.setUserInfo(JsonUtil.toJson(userInfo));
                bizActivitySeckillUserService.save(seckillUser);
            }

        } catch (Exception e) {
            throw e;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public List<Map<String, Object>> getMySeckillRecords(Long busiId) {
        List<BizActivitySeckillCondition> seckillConditions = this.getMySeckillCondition(busiId);
        ObjectMapper om = new ObjectMapper();
        List<Map<String, Object>> result = new ArrayList<>();
        List<Long> seckillIds = seckillConditions.stream().map(BizActivitySeckillCondition::getId).collect(Collectors.toList());
        if (seckillIds.size() == 0)
            return new ArrayList<>();
        List<BizActivitySeckillGift> seckillGifts = bizActivitySeckillGiftService.list(new QueryWrapper<BizActivitySeckillGift>()
                .in("SeckillId", seckillIds));
        Map<Long, List<Map<String, Object>>> giftsMap = new HashMap<>();
        seckillGifts.forEach(g -> {
            Long skId = g.getSeckillId();
            giftsMap.computeIfAbsent(skId, k -> new ArrayList<>());
            Map gift = om.convertValue(g, Map.class);
            giftsMap.get(skId).add(gift);
        });

        // 查询各个秒杀活动的参与用户数
        List<Map<String, Object>> countMapList = bizActivitySeckillUserService.getUserCountBySeckillIds(seckillIds);
        Map<Long, Integer> countMap = new HashMap<>();
        countMapList.forEach(c -> countMap.put(MapUtils.getLong(c, "seckillId"), MapUtils.getInteger(c, "userCount")));

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        seckillConditions.forEach(skc -> {
            LocalDateTime ldt = skc.getCreateTime();
            String createTime = ldt.format(formatter);

            Integer markCode = skc.getMarkCode();
            Map<String, Object> eMap = om.convertValue(skc, Map.class);
            eMap.put("createTime", createTime);
            Long seckillId = skc.getId();

            // 解析参与角色
            Integer partInRoles = skc.getPartInRoles();
            List<Integer> skRoles = new ArrayList<>();
            Collections.addAll(skRoles, 1, 2, 4, 8, 16);
            skRoles.removeIf(role -> (role & partInRoles) == 0);
            List<String> skRolesName = new ArrayList<>();
            skRoles.forEach(role -> {
                switch (role) {
                    case 1:
                        skRolesName.add("水果种植户"); break;
                    case 2:
                        skRolesName.add("分拣厂商"); break;
                    case 4:
                        skRolesName.add("农资厂商"); break;
                    case 8:
                        skRolesName.add("包装物厂商"); break;
                    case 16:
                        skRolesName.add("水果采购商"); break;
                    default:
                }
            });
            eMap.put("partInRoles", skRolesName);

            // 市场名称
            String markName = MapUtils.getString(marketUtil.getMarketByCode(markCode), "markName");
            eMap.put("markName", markName);
            // 秒杀礼物信息
            List<Map<String, Object>> giftInfos = rpcService.getGiftInfo(3);

            List<Map<String, Object>> gifts = giftsMap.get(seckillId);
            // 该次秒杀是否存在礼物购买
            boolean hasBuy = false;
            if (gifts != null) {
                for (Map<String, Object> g : gifts) {
                    Long giftId = MapUtils.getLong(g, "giftId");
                    if (MapUtils.getInteger(g, "buyNum") > 0)
                        hasBuy = true;
                    Optional<Map<String, Object>> giftInfo = giftInfos.stream().filter(info -> MapUtils.getLong(info, "Id").equals(giftId)).findFirst();
                    if (giftInfo.isPresent()) {
                        Map<String, Object> info = giftInfo.get();
                        g.put("giftName", MapUtils.getString(info, "ServName"));
                        g.put("giftPrice", MapUtils.getInteger(info, "Amount"));
                        g.put("giftPic", MapUtils.getString(info, "ServPic"));
                        g.remove("createTime");
                        g.remove("updateTime");
                    }

                }

                eMap.put("gifts", gifts);
                eMap.put("hasBuy", hasBuy);
            }



            // 参与用户数
            Integer userNum = countMap.get(seckillId);
            if (userNum != null)
                eMap.put("userNum", userNum);
            else
                eMap.put("userNum", 0);

            result.add(eMap);
        });
        return result;
    }

    @Override
    public List<BizActivitySeckillCondition> getMySeckillCondition(Long busiId) {
        return mapper.getMySeckillCondition(busiId);
    }

    @Override
    public List<Map<String, Object>> getSeckillUsersDetail(Long seckillId, Page page) {
        List<Map<String, Object>> data = bizActivitySeckillUserService
                .pageMaps(page, new QueryWrapper<BizActivitySeckillUser>().eq("SeckillId", seckillId))
                .getRecords();
        List<Map<String, Object>> result = new ArrayList<>();

        List<Map<String, Object>> giftInfos = rpcService.getGiftInfo(3);

        data.forEach(m -> {
            String userInfo = MapUtils.getString(m, "UserInfo");
            m.put("UserInfo", JsonUtil.jsonToMap(userInfo));

            Long giftId = MapUtils.getLong(m, "GiftId");
            Optional<Map<String, Object>> giftInfo = giftInfos.stream().filter(info -> MapUtils.getLong(info, "Id").equals(giftId)).findFirst();
            if (giftInfo.isPresent()) {
                Map<String, Object> g = giftInfo.get();
                m.put("giftName", MapUtils.getString(g, "ServName"));
                m.put("amount", MapUtils.getInteger(g, "Amount"));
            }
            result.add(SpecialMapUtil.lowKey(m));
        });
        return result;
    }

    @Override
    public Integer hasSeckillOrGiving(Long userId, Integer busiType, Long busiId) {
        if (busiType == 1)
            return 0;
        // seckill
        boolean hasSeckill = false;
        List<Integer> markCodes = marketClient.getMarkCodesByBusiId(busiId, busiType);
        if (markCodes == null || markCodes.size() == 0) {
            hasSeckill = false;
        } else {
            List<BizActivitySeckillCondition> secKillConditions = bizActivitySeckillConditionService.list(
                    new QueryWrapper<BizActivitySeckillCondition>().in("MarkCode", markCodes));

            // 不显示该用户已领取礼物的
            List<BizActivitySeckillUser> bizActivitySeckillUserList = bizActivitySeckillUserService
                    .list(new QueryWrapper<BizActivitySeckillUser>().eq("UserId",userId));
            List<Long> partInSeckillIds = new ArrayList<>();
            bizActivitySeckillUserList.forEach(r -> partInSeckillIds.add(r.getSeckillId()));

            Iterator<BizActivitySeckillCondition> iterator = secKillConditions.iterator();
            Integer role = BusinessUtil.busiType2Bin(busiType);
            List<Long> secKillIds = new ArrayList<>();
            while (iterator.hasNext()) {
                BizActivitySeckillCondition seckillCondition = iterator.next();
                if ((seckillCondition.getPartInRoles() & role) != 0 && !partInSeckillIds.contains(seckillCondition.getId()))
                    secKillIds.add(seckillCondition.getId());
            }

            // 过滤出已经到达开始时间的秒杀
            int onTimeSeckills = 0;
            if (secKillIds.size() > 0) {
                onTimeSeckills = this.count(new QueryWrapper<BizActivitySeckill>()
                        .in("Id", secKillIds)
                        .eq("GiftRemaining", 1)
                        .lt("StartTime", DateUtil.nowLdt()));

                if (onTimeSeckills > 0)
                    hasSeckill = true;
            }
        }

        // giving
        int giveCount = bizGiveGiftService.count(new QueryWrapper<BizGiveGift>()
                .eq("ReceId", userId)
                .eq("Received", 0));

        boolean hasGave = false;
        if (giveCount > 0)
            hasGave = true;

        if (!hasSeckill && !hasGave)
            return 0;
        else if (hasSeckill && !hasGave)
            return 1;
        else if (!hasSeckill && hasGave)
            return 2;
        else
            return 3;
    }


}
